import { EntityNode } from './EntityNode';
import { registryNodeSystem } from './Registry';

/**
 * NodeSystem类：游戏系统的基类，负责管理和处理实体节点的行为和状态
 * 系统可以包含多个实体节点，并通过生命周期方法来处理这些节点
 * 系统之间可以建立依赖关系，确保它们按照正确的顺序执行
 */
export class NodeSystem {
  // @ts-expect-error
  private _id = EntityNode.generateUUID();

  private _enable = true;
  private _entities: EntityNode[] = [];

  get id(): string {
    return this._id;
  }

  set enable(value: boolean) {
    if (this._enable === value) {
      console.warn('System.enable：值与当前值相同');
      return;
    }

    const oldValue = this._enable;
    this._enable = value;

    if (value && !oldValue) {
      this.onEnable?.();
    } else if (!value && oldValue) {
      this.onDisable?.();
    }
  }
  get enable(): boolean {
    return this._enable;
  }

  /**
   * 获取当前系统中所有实体节点
   *
   * @returns {EntityNode[]} 实体节点数组，是原始实体集合的一个浅拷贝
   */
  get entities(): EntityNode[] {
    return [...this._entities];
  }

  constructor() {
    this.onLoad?.();
    registryNodeSystem.set(this._id, this);
  }

  /**
   * 添加实体节点到系统中。当一个实体节点被添加后，系统将开始管理该节点，
   * 并在生命周期方法中处理该节点的相关逻辑
   *
   * @param entityNode 要添加的实体节点
   * @returns 返回系统实例，便于链式调用
   */
  addEntityNode(entityNode: EntityNode): this {
    if (!this._entities.includes(entityNode)) {
      this._entities.push(entityNode);
      this.onEntityNodeAdded?.(entityNode);
    }
    return this;
  }

  /**
   * 从系统中移除实体节点。当一个实体节点被移除后，系统将停止管理该节点，
   * 不再在生命周期方法中处理该节点的相关逻辑
   *
   * @param entityNode 要移除的实体节点
   * @returns 如果实体节点存在并成功移除则返回true，否则返回false
   */
  removeEntityNode(entityNode: EntityNode): boolean {
    const index = this._entities.indexOf(entityNode);
    if (index !== -1) {
      this._entities.splice(index, 1);
      this.onEntityNodeRemoved?.(entityNode);
      return true;
    }
    return false;
  }

  /**
   * 当实体节点成功被添加到系统时调用
   * @param entityNode 被添加的实体节点
   */
  protected onEntityNodeAdded?(entityNode: EntityNode): void {}

  /**
   * 当实体节点成功从系统中移除时调用
   * @param entityNode 被移除的实体节点
   */
  protected onEntityNodeRemoved?(entityNode: EntityNode): void {}

  /**
   * 系统初始化函数，在系统被注册到注册表之前调用
   * 子类可以重写此方法以执行必要的初始化操作，如设置初始状态、加载资源等
   */
  protected onLoad?(): void {}

  /**
   * 系统启用时调用，当系统的enable属性从false变为true时触发
   * 子类可以重写此方法以在系统启用时执行必要的操作
   */
  protected onEnable?(): void {}

  /**
   * 系统禁用时调用，当系统的enable属性从true变为false时触发
   * 子类可以重写此方法以在系统禁用时执行必要的清理操作
   */
  protected onDisable?(): void {}

  /**
   * 系统的帧更新函数，在每一帧中在所有组件的update之后被调用
   * 用于处理系统级别的逻辑，如实体间的交互、全局状态更新等
   *
   * @param deltaTime 距离上一帧的时间增量（以毫秒为单位）
   */
  protected update?(deltaTime: number): void {}

  /**
   * 系统的帧后处理函数，在每一帧中在所有组件的lateUpdate之后被调用
   * 用于处理需要在所有更新完成后进行的操作，如相机跟随、状态同步等
   *
   * @param deltaTime 距离上一帧的时间增量（以毫秒为单位）
   */
  protected postUpdate?(deltaTime: number): void {}

  /**
   * 销毁系统，清理所有资源和引用
   * 包括：清理依赖关系、调用禁用回调、清理实体引用、从注册表中移除等
   *
   * @throws 如果在销毁过程中发生错误，将在控制台输出错误信息
   */
  destroy(): void {
    try {
      // 调用禁用和销毁回调
      if (this._enable) {
        this.onDisable?.();
      }
      this.onDestroy?.();

      // 清理实体和注册信息
      this._entities = [];
      this._enable = false;
      registryNodeSystem.delete(this._id);
    } catch (error) {
      console.error(`销毁系统时出错 ${this._id}:`, error);
    }
  }

  /**
   * 系统销毁时调用，在系统被完全清理之前的最后一个生命周期方法
   * 子类可以重写此方法以执行自定义的清理操作
   */
  protected onDestroy?(): void {}
}
